package com.engine.salary.web;

import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.salaryacct.dto.*;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salarysob.dto.SalarySobCycleDTO;
import com.engine.salary.enums.salarysob.SalaryEmployeeStatusEnum;
import com.engine.salary.service.SalaryAcctExcelService;
import com.engine.salary.service.impl.SalaryAcctExcelServiceImpl;
import com.engine.salary.util.ResponseResult;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.excel.ExcelPreviewDTO;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.wrapper.*;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import weaver.hrm.HrmUserVarify;
import weaver.hrm.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 薪资核算
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
@Slf4j
public class SalaryAcctController {

    private SalaryAcctRecordWrapper getSalaryAcctRecordWrapper(User user) {
        return ServiceUtil.getService(SalaryAcctRecordWrapper.class, user);
    }

    private SalaryAcctEmployeeWrapper getSalaryAcctEmployeeWrapper(User user) {
        return ServiceUtil.getService(SalaryAcctEmployeeWrapper.class, user);
    }

    private SalaryAcctResultWrapper getSalaryAcctResultWrapper(User user) {
        return ServiceUtil.getService(SalaryAcctResultWrapper.class, user);
    }

    //    private SalaryAcctCheckResultWrapper salaryAcctCheckResultWrapper;
    private SalaryComparisonResultWrapper getSalaryComparisonResultWrapper(User user) {
        return ServiceUtil.getService(SalaryComparisonResultWrapper.class, user);
    }

    private SalaryAcctExcelWrapper getSalaryAcctExcelWrapper(User user) {
        return ServiceUtil.getService(SalaryAcctExcelWrapper.class, user);
    }

    private SalaryAcctExcelService getSalaryAcctExcelService(User user) {
        return ServiceUtil.getService(SalaryAcctExcelServiceImpl.class, user);
    }

//    /**********************************薪资核算记录相关 start*********************************/

    //薪资核算列表
    @POST
    @Path("/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String list(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctRecordQueryParam queryParam) {
        User user = HrmUserVarify.getUser(request, response);
        queryParam.setStartMonth(SalaryDateUtil.String2YearMonth(queryParam.getStartMonthStr()));
        queryParam.setEndMonth(SalaryDateUtil.String2YearMonth(queryParam.getEndMonthStr()));
        return new ResponseResult<SalaryAcctRecordQueryParam, PageInfo>(user).run(getSalaryAcctRecordWrapper(user)::listPage, queryParam);
    }

    //薪资核算详情
    @GET
    @Path("/getForm")
    @Produces(MediaType.APPLICATION_JSON)
    public String getForm(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Map<String, Object>>(user).run(getSalaryAcctRecordWrapper(user)::getForm, id);
    }

    //获取薪资核算的薪资周期、考勤周期等
    @GET
    @Path("/getSalarySobCycle")
    @Produces(MediaType.APPLICATION_JSON)
    public String getSalarySobCycle(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, SalarySobCycleDTO>(user).run(getSalaryAcctRecordWrapper(user)::getSalarySobCycleById, salaryAcctRecordId);
    }

    //保存薪资核算的基本信息
    @POST
    @Path("/basic/save")
    @Produces(MediaType.APPLICATION_JSON)
    public String save(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctRecordSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        param.setSalaryMonth(SalaryDateUtil.String2YearMonth(param.getSalaryMonthStr()));
        return new ResponseResult<SalaryAcctRecordSaveParam, Long>(user).run(getSalaryAcctRecordWrapper(user)::save, param);
    }

    //删除薪资核算记录
    @POST
    @Path("/delete")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteSalaryAcctRecord(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody Collection<Long> ids) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Collection<Long>, Long>(user).run(getSalaryAcctRecordWrapper(user)::delete, ids);
    }


    //归档薪资核算记录
    @GET
    @Path("/file")
    @Produces(MediaType.APPLICATION_JSON)
    public String fileSalaryAcctRecord(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Long>(user).run(getSalaryAcctRecordWrapper(user)::file, id);
    }

    //重新核算
    @POST
    @Path("/reAccounting")
    @Produces(MediaType.APPLICATION_JSON)
    public String reAccounting(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctRecordReAccountParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Long>(user).run(getSalaryAcctRecordWrapper(user)::reCalculate, param.getSalaryAcctRecordId());
    }

    //判断是否存在合并计税
    @GET
    @Path("/hasConsolidatedTax")
    @Produces(MediaType.APPLICATION_JSON)
    public String hasConsolidatedTax(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Integer>(user).run(getSalaryAcctRecordWrapper(user)::hasConsolidatedTax, id);
    }

    // 回算
    @POST
    @Path("/backCalculate")
    public String backCalculate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctRecordReAccountParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, String>(user).run(getSalaryAcctRecordWrapper(user)::backCalculate, param.getSalaryAcctRecordId());
    }

    /**
     * 检查薪资核算的账套配置是否发生变更
     *
     * @param id 薪资核算记录id
     * @return
     */
    @GET
    @Path("/compareSobConfig")
    @Produces(MediaType.APPLICATION_JSON)
    public String compareSobConfig(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Boolean>(user).run(getSalaryAcctRecordWrapper(user)::compareSobConfig, id);
    }

    /**
     * 更新薪资核算的账套配置
     *
     * @param id 薪资核算记录id
     * @return
     */
    @GET
    @Path("/updateSobConfig")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateSobConfig(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Boolean>(user).run(getSalaryAcctRecordWrapper(user)::updateSobConfig, id);
    }


    /* ********************************薪资核算记录相关 end*********************************/


    /**********************************薪资核算人员相关 start*********************************/

    //薪资核算人员确认列表
    @POST
    @Path("/acctemployee/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String listSalaryAccountingEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeQueryParam, PageInfo<SalaryAccEmployeeListDTO>>(user).run(getSalaryAcctEmployeeWrapper(user)::listPage, param);
    }

    //薪资核算环比上期减少人员列表
    @POST
    @Path("/reducedemployee/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String listReducedEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeQueryParam, PageInfo<SalaryAccEmployeeListDTO>>(user).run(getSalaryAcctEmployeeWrapper(user)::listPage4Reduce, param);
    }

    //薪资核算环比上期添加人员列表
    @POST
    @Path("/addedemployee/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String listAddEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeQueryParam, PageInfo<SalaryAccEmployeeListDTO>>(user).run(getSalaryAcctEmployeeWrapper(user)::listPage4Add, param);
    }


    //添加薪资核算人员
    @POST
    @Path("/acctemployee/save")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveSalaryAcctEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeSaveParam, String>(user).run(getSalaryAcctEmployeeWrapper(user)::save, param);
    }

    //删除薪资核算人员
    @POST
    @Path("/acctemployee/delete")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteSalaryAcctEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeDeleteParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeDeleteParam, String>(user).run(getSalaryAcctEmployeeWrapper(user)::delete, param);
    }

    //检查薪资核算人员的个税扣缴义务人
    @POST
    @Path("/acctemployee/checkTaxAgent")
    @Produces(MediaType.APPLICATION_JSON)
    public String checkTaxAgent(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmpCheckTaxAgentParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, String>(user).run(getSalaryAcctEmployeeWrapper(user)::checkTaxAgent, param.getSalaryAcctRecordId());
    }

    //刷新薪资核算人员
    @POST
    @Path("/acctemployee/refresh")
    @Produces(MediaType.APPLICATION_JSON)
    public String refreshTaxAgent(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmpRefreshTaxAgentParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, String>(user).run(getSalaryAcctEmployeeWrapper(user)::refresh, param.getSalaryAcctRecordId());
    }

    //从环比上月减少添加薪资核算人员
    @POST
    @Path("/acctemployee/addFromReduce")
    @Produces(MediaType.APPLICATION_JSON)
    public String addFromReduce(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctEmployeeAddParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctEmployeeAddParam, String>(user).run(getSalaryAcctEmployeeWrapper(user)::addFromReduce, param);
    }

    /**
     * 导出人员范围
     */
    @GET
    @Path("/acctemployee/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportSalaryAcctEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);

            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportSalaryAcctEmployee(param);
            String time = LocalDate.now().toString();
            String fileName = "核算人员范围" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("核算人员范围导出异常", e);
            throw e;
        }


    }

    @NotNull
    private SalaryAcctEmployeeQueryParam buildSalaryAcctEmployeeQueryParam(HttpServletRequest request) {
        SalaryAcctEmployeeQueryParam param = new SalaryAcctEmployeeQueryParam();

        String salaryAcctRecordId = request.getParameter("salaryAcctRecordId");
        if (StringUtils.isNotBlank(salaryAcctRecordId)) {
            param.setSalaryAcctRecordId(Long.parseLong(salaryAcctRecordId));
        }
        String employeeName = request.getParameter("employeeName");
        if (StringUtils.isNotBlank(employeeName)) {
            param.setEmployeeName(employeeName);
        }
        String taxAgentId = request.getParameter("taxAgentId");
        if (StringUtils.isNotBlank(taxAgentId)) {
            param.setTaxAgentId(Long.parseLong(taxAgentId));
        }
        String departmentIds = request.getParameter("departmentIds");
        if (StringUtils.isNotBlank(departmentIds)) {
            param.setDepartmentIds(Arrays.stream(departmentIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        String positionIds = request.getParameter("positionIds");
        if (StringUtils.isNotBlank(positionIds)) {
            param.setPositionIds(Arrays.stream(positionIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        String statuses = request.getParameter("statuses");
        if (StringUtils.isNotBlank(statuses)) {
            param.setStatuses(Arrays.stream(statuses.split(",")).map(String::valueOf).collect(Collectors.toList()));
        }
        //fixme 日期
        request.getParameter("dismissDate");
        String ids = request.getParameter("ids");
        if (StringUtils.isNotBlank(ids)) {
            param.setIds(Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        return param;
    }

    /**
     * 导出环比减少人员
     */
    @GET
    @Path("/reducedemployee/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportReducedEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportReducedEmployee(param);
            String time = LocalDate.now().toString();
            String fileName = "环比上月减少人员" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("环比上月减少人员导出异常", e);
            throw e;
        }
    }


    /**
     * 导出环比增加人员
     */
    @GET
    @Path("/addedemployee/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportAddedEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportAddedEmployee(param);
            String time = LocalDate.now().toString();
            String fileName = "环比上月增加人员" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("环比上月增加人员导出异常", e);
            throw e;
        }
    }


    // **********************************薪资核算人员相关 end*********************************/

    // **********************************薪资核算结果 start*********************************/
    @GET
    @Path("/acctresult/checkAuth")
    @Produces(MediaType.APPLICATION_JSON)
    public String checkAuth(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam("salaryAcctRecordId") Long salaryAcctRecordId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Boolean>(user).run(getSalaryAcctResultWrapper(user)::checkAuth, salaryAcctRecordId);
    }

    //薪资核算结果列表
    @POST
    @Path("/acctresult/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String listSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultQueryParam, Map<String, Object>>(user).run(getSalaryAcctResultWrapper(user)::listPage, param);
    }

    //合计行
    @POST
    @Path("/acctresult/sum")
    @Produces(MediaType.APPLICATION_JSON)
    public String sumSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultQueryParam, Map<String, Object>>(user).run(getSalaryAcctResultWrapper(user)::sumSalaryAcctResult, param);
    }


    //薪资核算结果详情
    @GET
    @Path("/acctresult/detail")
    @Produces(MediaType.APPLICATION_JSON)
    public String getSalaryAcctResultDetail(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, SalaryAcctResultDetailDTO>(user).run(getSalaryAcctResultWrapper(user)::getForm, id);
    }

    //薪资核算结果详情
    @GET
    @Path("/acctresult/getConsolidatedTaxDetail")
    @Produces(MediaType.APPLICATION_JSON)
    public String getConsolidatedTaxDetail(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "salaryAcctEmpId") Long salaryAcctEmpId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, ConsolidatedTaxDetailDTO>(user).run(getSalaryAcctResultWrapper(user)::getConsolidatedTaxDetail, salaryAcctEmpId);
    }

    //根据薪资核算记录id获取表头数据
    @GET
    @Path("/acctresult/getColumnDesc")
    @Produces(MediaType.APPLICATION_JSON)
    public String getColumnDesc(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Map<String, SalaryAcctResultListColumnDTO>>(user).run(getSalaryAcctResultWrapper(user)::getColumnBySalaryAcctRecordId, salaryAcctRecordId);
    }

    //编辑薪资核算结果
    @POST
    @Path("/acctresult/save")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultSaveParam, String>(user).run(getSalaryAcctResultWrapper(user)::save, param);
    }


    @POST
    @Path("/acctresult/lock")
    @Produces(MediaType.APPLICATION_JSON)
    public String lock(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultLockParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultLockParam, String>(user).run(getSalaryAcctResultWrapper(user)::lock, param);
    }

    //更新薪资项目锁定状态
    @POST
    @Path("/acctresult/updateLockStatus")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateLockStatus(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultUpdateLockStatusParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultUpdateLockStatusParam, String>(user).run(getSalaryAcctResultWrapper(user)::updateLockStatusByParam, param);
    }

    @POST
    @Path("/acctresult/lockEmp")
    @Produces(MediaType.APPLICATION_JSON)
    public String lock(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultUpdateLockStatusParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultUpdateLockStatusParam, String>(user).run(getSalaryAcctEmployeeWrapper(user)::lockEmp, param);
    }

    //批量更新
    @POST
    @Path("/acctresult/batchUpdate")
    @Produces(MediaType.APPLICATION_JSON)
    public String batchUpdate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultBatchUpdateParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultBatchUpdateParam, String>(user).run(getSalaryAcctResultWrapper(user)::batchUpdate, param);
    }

    //薪资核算
    @POST
    @Path("/acctresult/accounting")
    @Produces(MediaType.APPLICATION_JSON)
    public String accounting(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctCalculateParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctCalculateParam, String>(user).run(getSalaryAcctResultWrapper(user)::calculate, param);
    }

    //导出核算结果
    @GET
    @Path("/acctresult/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctResultQueryParam param = new SalaryAcctResultQueryParam();
            setSalaryAcctResultQueryParam(request, param);
            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportSalaryAcctResult(param);
            String fileName = "薪资核算结果" + LocalDate.now();
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("薪资核算结果导出异常", e);
            throw e;
        }
    }

    //导出核算结果(自定义导出字段)
    @GET
    @Path("/acctresult/exportWithCustomFields")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportSalaryAcctResultWithCustomFields(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctResultQueryParam param = new SalaryAcctResultQueryParam();
            setSalaryAcctResultQueryParam(request, param);
            //设置自定义导出字段
            String salaryItemIds = request.getParameter("salaryItemIds");
            if (StringUtils.isNotBlank(salaryItemIds)) {
                param.setSalaryItemIds(Arrays.stream(salaryItemIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
            }
            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportSalaryAcctResult(param);
            String fileName = "薪资核算结果" + LocalDate.now();
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("薪资核算结果导出异常", e);
            throw e;
        }
    }


    //导入核算结果前生成导入模板时可选的薪资项目
    @GET
    @Path("/acctresult/importField")
    @Produces(MediaType.APPLICATION_JSON)
    public String accounting(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, SalaryAcctImportFieldDTO>(user).run(getSalaryAcctExcelService(user)::getImportField, salaryAcctRecordId);
    }

    //导出核算结果前生成可选的薪资项目
    @GET
    @Path("/acctresult/exportField")
    @Produces(MediaType.APPLICATION_JSON)
    public String exportField(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, SalaryAcctImportFieldDTO>(user).run(getSalaryAcctExcelService(user)::getExportField, salaryAcctRecordId);
    }

    // 薪资核算导入字段缓存
    @POST
    @Path("/acctresult/cacheImportField")
    @Produces(MediaType.APPLICATION_JSON)
    public String cacheImportField(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultTemplateSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultTemplateSaveParam, String>(user).run(getSalaryAcctExcelService(user)::cacheImportField, param);
    }

    // 薪资核算导出字段缓存
    @POST
    @Path("/acctresult/cacheExportField")
    @Produces(MediaType.APPLICATION_JSON)
    public String cacheExportField(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctImportParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<List<Long>, String>(user).run(getSalaryAcctExcelService(user)::cacheExportField, param.getSalaryItems());
    }

    // 保存导出模板
    @POST
    @Path("/acctresult/saveExportTemplate")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveExportTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultTemplateSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultTemplateSaveParam, String>(user).run(getSalaryAcctExcelService(user)::saveExportTemplate, param);
    }

    // 删除导出模板
    @POST
    @Path("/acctresult/deleteExportTemplate")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteExportTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultTemplateSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<List<Long>, String>(user).run(getSalaryAcctExcelService(user)::deleteExportTemplate, param.getIds());
    }

    // 获取导出模板详细信息
    @POST
    @Path("/acctresult/getExportTemplateForm")
    @Produces(MediaType.APPLICATION_JSON)
    public String getExportTemplateForm(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultTemplateSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, Map<String, Object>>(user).run(getSalaryAcctExcelService(user)::getExportTemplateForm, param.getId());
    }

    // 获取导出模列表
    @POST
    @Path("/acctresult/exportTemplateList")
    @Produces(MediaType.APPLICATION_JSON)
    public String exportTemplateList(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultTemplateSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultTemplateSaveParam, Map<String, Object>>(user).run(getSalaryAcctExcelService(user)::exportTemplateList, param);
    }


    //导出导入模板
    @GET
    @Path("/acctresult/importtemplate/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportImportTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryAcctImportTemplateParam param = new SalaryAcctImportTemplateParam();
            setSalaryAcctResultQueryParam(request, param);

            String importType = request.getParameter("importType");
            if (StringUtils.isNotBlank(importType)) {
                param.setImportType(importType);
            }
            String salaryItemIds = request.getParameter("salaryItemIds");
            if (StringUtils.isNotBlank(salaryItemIds)) {
                param.setSalaryItemIds(Arrays.stream(salaryItemIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
            }

            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportImportTemplate(param);
            String time = LocalDate.now().toString();
            String fileName = "薪资核算导入模板" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("薪资核算导入模板导出异常", e);
            throw e;
        }

    }

    //导入核算结果
    @POST
    @Path("/acctresult/importSalaryAcctResult")
    @Produces(MediaType.APPLICATION_JSON)
    public String importSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctImportParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctImportParam, Map<String, Object>>(user).run(getSalaryAcctExcelService(user)::importSalaryAcctResult, param);
    }

    @POST
    @Path("/acctresult/preview")
    @Produces(MediaType.APPLICATION_JSON)
    public String importSalaryAcctResultPreview(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctImportParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctImportParam, ExcelPreviewDTO>(user).run(getSalaryAcctExcelService(user)::previewImportSalaryAcctResult, param);
    }

    // **********************************薪资核算结果 end*********************************/

    // **********************************检验异常 start*********************************/

//    @GetMapping("/checkresult/getCount")
//    @ApiOperation(("获取校验结果（异常）总数"))
//    @WeaPermission
//    public WeaResult<Integer> getCheckResultCount(@RequestParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
//        Integer salaryCheckResultCount = salaryAcctCheckResultWrapper.countBySalaryAcctRecordId(salaryAcctRecordId, TenantContext.getCurrentTenantKey());
//        return WeaResult.success(salaryCheckResultCount);
//    }
//
//    @PostMapping("/checkresult/list")
//    @ApiOperation("校验结果列表")
//    @WeaPermission
//    public WeaResult<WeaTable<SalaryCheckResultListDTO>> listCheckResult(@RequestBody @Validated SalaryCheckResultQueryParam queryParam) {
//        WeaTable<SalaryCheckResultListDTO> weaTable = salaryAcctCheckResultWrapper.listPage(queryParam, TenantContext.getCurrentTenantKey());
//        return WeaResult.success(weaTable);
//    }
//
//    @PostMapping("/checkresultdetail/list")
//    @ApiOperation("校验结果明细列表")
//    @WeaPermission
//    public WeaResult<WeaTable<SalaryCheckResultRecordListDTO>> listCheckResultRecord(@RequestBody @Validated SalaryCheckResultRecordQueryParam queryParam) {
//        WeaTable<SalaryCheckResultRecordListDTO> weaTable = salaryAcctCheckResultWrapper.listPage4CheckResultRecord(queryParam, TenantContext.getCurrentTenantKey());
//        return WeaResult.success(weaTable);
//    }
//
//    @PostMapping("/checkresult/ignore")
//    @ApiOperation("校验结果列表")
//    @WeaPermission
//    public WeaResult<Object> ignoreCheckResult(@RequestParam(value = "id") Long id) {
//        salaryAcctCheckResultWrapper.ignoreById(id, TenantContext.getCurrentTenantKey());
//        return WeaResult.success(null);
//    }
//
//    @PostMapping("/checkresult/ignoreAll")
//    @ApiOperation("校验结果列表")
//    @WeaPermission
//    public WeaResult<Object> ignoreAllCheckResult(@RequestParam(value = "salaryAcctRecordId") Long salaryAcctRecordId) {
//        salaryAcctCheckResultWrapper.ignoreBySalaryAcctRecordId(salaryAcctRecordId, TenantContext.getCurrentTenantKey());
//        return WeaResult.success(null);
//    }
//
//    @PostMapping("/acctresult/check")
//    @ApiOperation(("薪资核算结果校验"))
//    @WeaPermission
//    public WeaResult<Object> check(@RequestBody @Validated SalaryAcctCheckParam checkParam) {
//        salaryAcctResultWrapper.check(checkParam, UserContext.getCurrentUser(), TenantContext.getCurrentTenantKey());
//        return WeaResult.success(null);
//    }
//
//    @PostMapping("/checkresult/export")
//    @ApiOperation("校验异常导出")
//    @WeaPermission
//    public WeaResult<Map<String, Object>> exportCheckResult(@RequestBody @Validated SalaryCheckResultExportParam exportParam) {
//        DataCollectionEmployee simpleEmployee = UserContext.getCurrentUser();
//        String tenantKey = TenantContext.getCurrentTenantKey();
//        String eteamsId = TenantRpcContext.getEteamsId();
//        Map<String, Object> map = salaryAcctExcelWrapper.exportCheckResult(exportParam, simpleEmployee, tenantKey, eteamsId);
//        return WeaResult.success(map);
//    }
//
//    @PostMapping("/checkresultRecord/export")
//    @ApiOperation("校验异常明细导出")
//    @WeaPermission
//    public WeaResult<Map<String, Object>> exportCheckResultDetail(@RequestParam(value = "checkResultId") Long checkResultId) {
//        DataCollectionEmployee simpleEmployee = UserContext.getCurrentUser();
//        String tenantKey = TenantContext.getCurrentTenantKey();
//        String eteamsId = TenantRpcContext.getEteamsId();
//        Map<String, Object> map = salaryAcctExcelWrapper.exportCheckResultDetail(checkResultId, simpleEmployee, tenantKey, eteamsId);
//        return WeaResult.success(map);
//    }
//
    // **********************************检验异常 end*********************************/

    // **********************************线下对比 start*********************************/

    //线上线下对比结果列表
    @POST
    @Path("/comparisonresult/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String listComparisonResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryComparisonResultQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryComparisonResultQueryParam, Map<String, Object>>(user).run(getSalaryComparisonResultWrapper(user)::listPage, param);
    }


    //导出线上线下对比结果
    @GET
    @Path("/comparisonresult/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportComparisonResult(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            SalaryComparisonResultQueryParam param = new SalaryComparisonResultQueryParam();

            setSalaryAcctResultQueryParam(request, param);
            String onlyDiffEmployee = request.getParameter("onlyDiffEmployee");
            if (StringUtils.isNotBlank(onlyDiffEmployee)) {
                param.setOnlyDiffEmployee(Boolean.parseBoolean(onlyDiffEmployee));
            }
            String onlyDiffSalaryItem = request.getParameter("onlyDiffSalaryItem");
            if (StringUtils.isNotBlank(onlyDiffSalaryItem)) {
                param.setOnlyDiffSalaryItem(Boolean.parseBoolean(onlyDiffSalaryItem));
            }

            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportComparisonResult(param);
            String time = LocalDate.now().toString();
            String fileName = "线下对比结果" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("线下对比结果导出异常", e);
            throw e;
        }
    }

    private void setSalaryAcctResultQueryParam(HttpServletRequest request, SalaryAcctResultQueryParam param) {
        String salaryAcctRecordId = request.getParameter("salaryAcctRecordId");
        if (StringUtils.isNotBlank(salaryAcctRecordId)) {
            param.setSalaryAcctRecordId(Long.parseLong(salaryAcctRecordId));
        }
        String employeeName = request.getParameter("employeeName");
        if (StringUtils.isNotBlank(employeeName)) {
            param.setEmployeeName(employeeName);
        }
        String taxAgentId = request.getParameter("taxAgentId");
        if (StringUtils.isNotBlank(taxAgentId)) {
            param.setTaxAgentId(Long.parseLong(taxAgentId));
        }
        String departmentIds = request.getParameter("departmentIds");
        if (StringUtils.isNotBlank(departmentIds)) {
            param.setDepartmentIds(Arrays.stream(departmentIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        String positionIds = request.getParameter("positionIds");
        if (StringUtils.isNotBlank(positionIds)) {
            param.setPositionIds(Arrays.stream(positionIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        String status = request.getParameter("status");
        if (StringUtils.isNotBlank(status)) {
            param.setStatus(SalaryEmployeeStatusEnum.parseByValue(Integer.parseInt(status)));
        }
        String statuses = request.getParameter("statuses");
        if (StringUtils.isNotBlank(statuses)) {
            param.setStatuses(Arrays.stream(statuses.split(",")).map(String::valueOf).collect(Collectors.toList()));
        }
        //fixme 日期
        request.getParameter("dismissDate");
        String consolidatedTaxation = request.getParameter("consolidatedTaxation");
        if (StringUtils.isNotBlank(consolidatedTaxation)) {
            param.setConsolidatedTaxation(consolidatedTaxation);
        }
        String ids = request.getParameter("ids");
        if (StringUtils.isNotBlank(ids)) {
            param.setIds(Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
        String workcode = request.getParameter("workcode");
        if (StringUtils.isNotBlank(workcode)) {
            param.setWorkcode(workcode);
        }
        String subcompanyIds = request.getParameter("subcompanyIds");
        if (StringUtils.isNotBlank(subcompanyIds)) {
            param.setSubcompanyIds(Arrays.stream(subcompanyIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }
    }


    //线下对比结果导入模板导出
    @GET
    @Path("/comparisonresult/importtemplate/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportComparisonResultTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response) {

        try {
            SalaryComparisonResultExportParam param = new SalaryComparisonResultExportParam();
            String salaryAcctRecordId = request.getParameter("salaryAcctRecordId");
            if (StringUtils.isNotBlank(salaryAcctRecordId)) {
                param.setSalaryAcctRecordId(Long.parseLong(salaryAcctRecordId));
            }

            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getSalaryAcctExcelWrapper(user).exportComparisonResultTemplate(param);
            String time = LocalDate.now().toString();
            String fileName = "线下对比结果导入模板" + time;
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("线下对比结果导入模板导出异常", e);
            throw e;
        }
    }

    //导入线下核算结果
    @POST
    @Path("/comparisonresult/importExcelAcctResult")
    @Produces(MediaType.APPLICATION_JSON)
    public String importExcelAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctImportParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctImportParam, Map<String, Object>>(user).run(getSalaryAcctExcelService(user)::importExcelAcctResult, param);
    }

    @POST
    @Path("/comparisonresult/preview")
    @Produces(MediaType.APPLICATION_JSON)
    public String importExcelAcctResultPreview(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctImportParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctImportParam, Map<String, Object>>(user).run(getSalaryAcctExcelService(user)::preview, param);
    }

    /**********************************线下对比 end*********************************/

    /**
     * 儿科医院 保存反馈
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/acctresult/saveFeedback")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveFeedback(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultFeedBackParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultFeedBackParam, String>(user).run(getSalaryAcctResultWrapper(user)::saveFeedback, param);
    }

    /**
     * 儿科医院 删除反馈
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/acctresult/deleteFeedback")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteFeedback(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultFeedBackParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalaryAcctResultFeedBackParam, String>(user).run(getSalaryAcctResultWrapper(user)::deleteFeedback, param);
    }
}
